#include<stdio.h>
#include "../include/N_arytree.h"
#include "../include/errorcodes.h"

#define ERR_VFS_ADDFILE_02 "INVALID_CHARACTER_IN_FILENAME"
#define ERR_VFS_ADDFILE_03 "FILE_ALREADY_EXISTS"
#define ERR_VFS_ADDFILE_04 "FILE_SYSTEM_FULL"
//New
#define ERR_VFS_ADDFILE_05 "CANNOT_WRITE_TO_DATAFILE" 
//New : (if data exceeds block size)
#define ERR_VFS_ADDFILE_06 "FILE_TOO_LARGE"


void add_file(char *dirName, char *fileName, char *filePath)
{
		int isFileFull = 1;             //to keep track if the bitarray is full
		
		int isValid=checkNameValidity(fileName);
		if(isValid==0)
		{
			printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_02);
			return;
		}
		
		char * tdname;	
		tdname=(char *)malloc(sizeof(char)*50);

		strcpy(tdname,dirName);
		if(strcmp(tdname,"/") != 0)
			strcat(dirName,"/");
		strcat(dirName,fileName);

		fd *tempchk = bstSearchNode(&bstRoot,dirName);

		if(tempchk != NULL)
		{
			printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_03);
			return;
		}
		
		flist bitArray[header.maxNoOfFileDescriptor];
		int index=0,i=0,file_offset=0;
		int eof=-1,result=0,fsize=0;
		char ch='0';
		//create file descriptor
		fd *new=(fd *) malloc(sizeof(fd));
		new->fileType='F';
		strcpy(new->file_name,fileName);
		strcpy(new->path,tdname);
		
		//checking if dirName is a valid path
		//int insert = insert_node(&naryRoot,new);
		
		//read the file and put in string
		FILE *exfile=fopen(filePath,"r");

		if(exfile == NULL)
		{
			printf("addfile_FAILURE %s\n",ERR_VFS_LISTFILE_01);
			return;
		}
		//to check for input file size
		while((ch=fgetc(exfile))!=EOF)
		{
			fsize++;
			if(fsize > 1024)
			{
				printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_06);
				return;
			}
		}
		ch='0';
		fsize=0;
		fseek(exfile,0,SEEK_SET);		
		
		//search the freelist for empty block;write block in file block.
		
		FILE *fp=fopen(header.fileSystemLabel,"rb+");
		if(fp==NULL)
		{
			printf("addfile_FAILURE %s\n",ERR_VFS_MOUNT_02);
		}
		else
		{
			offset=0;

			while(ch!='$')
			{
				fread(&ch,sizeof(ch),1,fp);
				offset++;

			}


			fseek(fp,offset,SEEK_SET);
			fread(bitArray,sizeof(flist),header.maxNoOfFileDescriptor,fp);
			//printf("bit array in addfile=%c \n",bitArray[0].value);
			offset=0;
			
			for(i=0;i<header.maxNoOfFileDescriptor;i++)
			{
					if(bitArray[i].value == '0')
					{	//printf("\nIn if set\n");
						bitArray[i].value='1';
						isFileFull = 0;
						break;
					}
			}
			
			/*if(isFileFull == 1)
			{
				printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_04);
				return;
			}*/
			if(fdcounter >= header.maxNoOfFileDescriptor)
			{
				printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_04);
				return;
			}
			//printf("bit array in addfile after setting=%c \n",bitArray[0].value);

			fseek(fp,0,SEEK_SET);
			while(ch!='!')
			{
				fread(&ch,sizeof(ch),1,fp);
				file_offset++;
			}
			
		
			fseek(fp,(file_offset+(i*1024)),SEEK_SET);
			
			while((ch=fgetc(exfile))!=EOF)
			{
				//ch=fgetc(exfile);
				fwrite(&ch,sizeof(ch),1,fp);
				fsize++;
			}
			
			fputc(eof,fp);
		}
		


		new->blockNum=i;
		new->fileSize=fsize;

		int insert=0;
		insert = insert_node(&naryRoot,new);
		if(insert == 1)
		{
			printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_05);
			return;
		}

		//printf("Insert status=%d\n",insert);
		//printtree(naryRoot);
		bstInsertNode(&bstRoot,new);
		//print(bstRoot);
		hashInsert(hash,*new);


		
		fseek(fp,31,SEEK_SET);
		fwrite(bitArray,sizeof(flist),header.maxNoOfFileDescriptor,fp);
		
		
		//insert file descriptor in the narray,hashtable and binarytree
		

		//printtree(naryRoot);

		fclose(fp);
		fclose(exfile);
		printf("addfile_SUCCESS\n");
		
}
